#include <math.h>
#include <string.h>
#include <time.h>
#include <pcre.h>
typedef char* string;
#include "md5/md5sum.c"

int filesize(FILE* fp) {
    fseek(fp, 0, SEEK_END);
    int length = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    return length;
}

int pcre_match(string pattern, string subject, int** results) {
    /*PCRE regex*/
    const char* error;
    int         erroffset;
    pcre*       compiled_pattern;
    int         match_count;
    int         ovectsize;
    compiled_pattern = pcre_compile(pattern, 0, &error, &erroffset, 0); 
    if(!compiled_pattern) {
        return -1;
    }
    pcre_fullinfo(compiled_pattern, NULL, PCRE_INFO_CAPTURECOUNT, &ovectsize);
    ovectsize = (ovectsize + 1)*3;
    *results = (int*)malloc(sizeof(int)*ovectsize);
    match_count = pcre_exec(
        compiled_pattern,     /* the compiled pattern */
        0,                    /* no extra data - pattern was not studied */
        subject,              /* the string to match */
        strlen(subject),      /* the length of the string */
        0,                    /* start at offset 0 in the subject */
        0,                    /* default options */
        *results,             /* output vector for substring information */
        ovectsize);           /* number of elements in the output vector */
    if(match_count < 0) {
        return -1;
    }
    return match_count;
}

void printvect(int* v, int length) {
    int i;
    printf("[");
    for(i=0;i<length;i++) printf("%d ", v[i]);
    printf("]");
}

string timestamp() {
    time_t ltime = time(NULL); /* get current cal time */
    string s = asctime(localtime(&ltime));
    s[strlen(s)-1] = '\0';
    return s;
}

string bindump(string s) {
    int l = strlen(s);
	string dump = malloc(8*l + 1);
	int i=0, j;
	while(i<l) {
	    unsigned int c = (unsigned int)s[i];
	    j=8;
	    while(j-->0) {
		    dump[i*8 + j] = '0' | (c & 1);
		    c >>= 1;
	    }
	    i++;
	}
	dump[i*8] = '\0';
    return dump;
}

string getlongline(FILE* f) {
    size_t size = 0;
    size_t len  = 0;
    size_t last = 0;
    string buf  = NULL;

    do {
		size += BUFSIZ; 			/* BUFSIZ is defined as "the optimal read size for this platform" */
        buf = realloc(buf,size); 	/* realloc(NULL,n) is the same as malloc(n) */            
        fgets(buf+last, size, f);
        len = strlen(buf);
        last = len - 1;
    } while (!feof(f) && buf[last]!='\n');
    buf[last] = '\0';
    return buf;
}

int check_constraints(int argc, string* argv) {
	return 1; //assume input image is fine

	//Check if the program is called with exactly one argument (the full path of the image)
    if(--argc!=NUMARGS) {
        printf("Program must be invoked with an image as first and only argument.\n");
        return 0;
    } else {
        system("clear");
    }
    
    //Open original image (guessing image format from its extension) and check constraints
    image orig;
    image source;
    if(!(orig = open_image(argv[1]))) {
        printf("Error reading from image file.\n");
        return 1;
    }
    if(!is_bitmap(orig)) {
        printf("This program is designed to work on uncompressed images (ie: bitmap images).\n");
        return 1;
    }
    if(orig->width < BLOCK_SIZE || orig->height < BLOCK_SIZE) {
        printf("Image must be at least %dx%d pixels.\n", BLOCK_SIZE, BLOCK_SIZE);
        return 1;
    }

    //Check if trimming is needed
    if(orig->width % BLOCK_SIZE || orig->height % BLOCK_SIZE) {
        printf("[%s] Image dimensions are not a multiple of %d pixels.\nImage will be trimmed and renamed with suffix \"%s\".\n", timestamp(), BLOCK_SIZE, TRIM_SUFFIX);
        source = bmp_trim(orig, BLOCK_SIZE);
        save_image(source);
    } else {
        source = orig;
    }
    printf("[%s] Original image's MD5 digest: %s.\n", timestamp(), source->md5sum);
}
